{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d90cbc83",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "#from vk_download import main\n",
    "import scipy.sparse as sprs\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import os\n",
    "import time\n",
    "import pandas as pd\n",
    "import random\n",
    "import datetime\n",
    "from tqdm.auto import tqdm\n",
    "from threading import Thread\n",
    "from multiprocessing import Process\n",
    "import numpy as np\n",
    "from scipy.sparse import csr_matrix, lil_matrix\n",
    "import scipy.sparse as sprs\n",
    "import os\n",
    "from collections import OrderedDict\n",
    "import shutil\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "import networkx as nx\n",
    "from IPython.display import clear_output\n",
    "from statsmodels.stats.proportion import proportion_confint\n",
    "from scipy import stats\n",
    "import statsmodels.api as sm\n",
    "from scipy.optimize import minimize\n",
    "import statistics"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e419e70d-11a2-4ffd-bd66-a25dcff5c9a0",
   "metadata": {},
   "source": [
    "# Choose city"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "608a1dae-fc1b-47c4-b806-bbc1ef46f65e",
   "metadata": {},
   "outputs": [],
   "source": [
    "#folder = 'MainCity'  # This city was used in analysis\n",
    "\n",
    "# These two cities were used to check robustness of our results\n",
    "\n",
    "#folder = 'City(1)'  # Robustness 1\n",
    "#folder = 'City(2)'  # Robustness 2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "27dea59e-c97e-4f46-a1f0-84967fcdc98b",
   "metadata": {},
   "source": [
    "# Download data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c854f8e0-ec72-4b6a-9fde-03f22001a148",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "X = pd.read_csv(f'{folder}/UsersAttributesGiant.csv')\n",
    "A1 = sprs.load_npz(f'{folder}/AdjMatrix(1)Giant.npz')\n",
    "A2 = sprs.load_npz(f'{folder}/AdjMatrix(2)Giant.npz')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9276825b-55e4-43cc-8176-029fee15a7da",
   "metadata": {},
   "source": [
    "# ... and create networkx objects"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a6abcd1-447b-41e1-8ab2-2d0631645008",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create graphs from adjacency matrices\n",
    "\n",
    "G1 = nx.from_numpy_matrix(A1)\n",
    "\n",
    "G2 = nx.from_numpy_matrix(A2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a280515b-9816-4a1f-aa0e-56021306700c",
   "metadata": {},
   "source": [
    "# Find k-clique communities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4ec1d314-a633-4391-9559-2c6d70a9e4e7",
   "metadata": {},
   "outputs": [],
   "source": [
    "# set k\n",
    "\n",
    "k = 5\n",
    "\n",
    "c1 = list(nx.algorithms.community.k_clique_communities(G1, k))\n",
    "\n",
    "c2 = list(nx.algorithms.community.k_clique_communities(G2, k))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4a2dafda-9004-4856-8c4c-b7858a541641",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f'The number of {k}-clique communities at time t1: {len(c1)}')\n",
    "\n",
    "print('')\n",
    "\n",
    "print(f'The number of {k}-clique communities at time t2: {len(c2)}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1116022-ee44-4531-8577-ed8a40da8b54",
   "metadata": {},
   "source": [
    "# Ideologically homogeneous k-clique communities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "acc032d5-a775-4500-9652-5a67878aad7c",
   "metadata": {},
   "outputs": [],
   "source": [
    "Conservative_Chambers1 = []\n",
    "Liberal_Chambers1 = []\n",
    "\n",
    "\n",
    "th = 1\n",
    "\n",
    "for clique in c1:\n",
    "    \n",
    "    sample = np.array(list(clique))\n",
    "    \n",
    "    opinions = X['OpinionBefore'][sample]\n",
    "    \n",
    "    \n",
    "    if (sum(opinions > 0.6) == 0) & ((sum(opinions < 0.4) / len(opinions) >= th)):\n",
    "\n",
    "        Conservative_Chambers1.append(sample)\n",
    "        \n",
    "    elif (sum(opinions < 0.4) == 0) & ((sum(opinions > 0.6) / len(opinions) >= th)):\n",
    "        \n",
    "        Liberal_Chambers1.append(sample)\n",
    "                                       \n",
    "    else:\n",
    "                                       \n",
    "        pass\n",
    " \n",
    "\n",
    "#-----------------------------------------------------------------------------------------------\n",
    "    \n",
    "Conservative_Chambers2 = []\n",
    "Liberal_Chambers2 = []\n",
    "\n",
    "\n",
    "for clique in c2:\n",
    "    \n",
    "    sample = np.array(list(clique))\n",
    "    \n",
    "    opinions = X['OpinionAfter'][sample]\n",
    "\n",
    "    \n",
    "    if (sum(opinions > 0.6) == 0) & ((sum(opinions < 0.4) / len(opinions) >= th)):\n",
    "    \n",
    "        Conservative_Chambers2.append(sample)\n",
    "        \n",
    "    elif (sum(opinions < 0.4) == 0) & ((sum(opinions > 0.6) / len(opinions) >= th)):\n",
    "        \n",
    "        Liberal_Chambers2.append(sample)\n",
    "                                       \n",
    "    else:\n",
    "                                       \n",
    "        pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9bb76d75-3b2f-44ac-8d9c-2584cbe51bb6",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f'The number of conservative {k}-clique communities at time t1: {len(Conservative_Chambers1)}')\n",
    "\n",
    "print('')\n",
    "\n",
    "print(f'The number of liberal {k}-clique communities at time t1: {len(Liberal_Chambers1)}')\n",
    "\n",
    "print('')\n",
    "\n",
    "print('------------------------------------------')\n",
    "\n",
    "print('')\n",
    "\n",
    "print(f'The number of conservative {k}-clique communities at time t2: {len(Conservative_Chambers2)}')\n",
    "\n",
    "print('')\n",
    "\n",
    "print(f'The number of liberal {k}-clique communities at time t2: {len(Liberal_Chambers2)}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc983612-6808-4ae7-9123-6d1dd8f6554f",
   "metadata": {},
   "source": [
    "# The sizes of ideologically homogeneous k-clique communities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "caeffaee-fa2d-4578-8434-7184992f97c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "print('Conservative (t1):')\n",
    "\n",
    "pd.DataFrame([len(Conservative_Chambers1[i]) for i in range(len(Conservative_Chambers1))]).value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "62984e59-6d28-4111-80ca-2e5924f22929",
   "metadata": {},
   "outputs": [],
   "source": [
    "print('Conservative (t2):')\n",
    "\n",
    "pd.DataFrame([len(Conservative_Chambers2[i]) for i in range(len(Conservative_Chambers2))]).value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e5740559-655e-4c7c-9d7f-a755eb4a60bf",
   "metadata": {},
   "outputs": [],
   "source": [
    "print('Liberal (t1):')\n",
    "\n",
    "pd.DataFrame([len(Liberal_Chambers1[i]) for i in range(len(Liberal_Chambers1))]).value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "03d543a9-ee24-44f5-85a5-c61759e544de",
   "metadata": {},
   "outputs": [],
   "source": [
    "print('Liberal (t2):')\n",
    "\n",
    "pd.DataFrame([len(Liberal_Chambers2[i]) for i in range(len(Liberal_Chambers2))]).value_counts()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57c8f517-ee74-4f09-8bee-19193ecd8ac5",
   "metadata": {},
   "source": [
    "# Compare demographical compositions of liberal and conservative k-clique communities"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b465d551-f43d-404f-a93e-3a9a7ef8fb8f",
   "metadata": {},
   "outputs": [],
   "source": [
    "stds = []\n",
    "means = []\n",
    "\n",
    "for i in Conservative_Chambers1:\n",
    "    \n",
    "    sample = np.array(i)\n",
    "    \n",
    "    means.append((X['age'][sample]).mean())\n",
    "    stds.append((X['age'][sample]).std())\n",
    "\n",
    "print('Mean age averaged over conservative communities (time t1):', round(np.array(means).mean(), 3)) \n",
    "print('Std of age averaged over conservative communities (time t1):', round(np.array(stds).mean(), 3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5ab05497-2851-492d-b883-183c45f02580",
   "metadata": {},
   "outputs": [],
   "source": [
    "stds = []\n",
    "means = []\n",
    "\n",
    "for i in Liberal_Chambers1:\n",
    "    \n",
    "    sample = np.array(i)\n",
    "    \n",
    "    means.append((X['age'][sample]).mean())\n",
    "    stds.append((X['age'][sample]).std())\n",
    "\n",
    "print('Mean age averaged over liberal communities (time t1):', round(np.array(means).mean(), 3)) \n",
    "print('Std of age averaged over liberal communities (time t1):', round(np.array(stds).mean(), 3))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ab5d3938-055b-44e8-ba7b-d754af1873ac",
   "metadata": {},
   "source": [
    "# The null models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "298c2052-b464-4e7a-a07e-3d55f75e954b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def average_cliques_ER(k, N, p):\n",
    "    perm_N_k = 1\n",
    "    for i in range(k):\n",
    "        perm_N_k *= N-i\n",
    "    perm_N_k /= k\n",
    "    clique_p = p**(k*(k-1)/2)\n",
    "    avg = perm_N_k * clique_p\n",
    "    return avg, avg**0.5\n",
    "\n",
    "\n",
    "def avg_community_size(com):\n",
    "    a = .0\n",
    "    for c in com:\n",
    "        a += len(c)\n",
    "    a /= len(com)\n",
    "    return a\n",
    "\n",
    "\n",
    "def communities_stats(g, opinion_list, k):\n",
    "    result = {}\n",
    "    top_nodes = []\n",
    "    bottom_nodes = []\n",
    "    for i in range(len(opinion_list)):\n",
    "        if opinion_list[i] > 0.6:\n",
    "            top_nodes.append(i)\n",
    "        elif opinion_list[i] < 0.4:\n",
    "            bottom_nodes.append(i)\n",
    "    g_top = g.subgraph(top_nodes)\n",
    "    g_bottom = g.subgraph(bottom_nodes)\n",
    "    \n",
    "    p = 2*g.number_of_edges()/(g.number_of_nodes()*(g.number_of_nodes()-1))\n",
    "    p_top = 2*g_top.number_of_edges()/(g_top.number_of_nodes()*(g_top.number_of_nodes()-1))\n",
    "    p_bottom = 2*g_bottom.number_of_edges()/(g_bottom.number_of_nodes()*(g_bottom.number_of_nodes()-1))\n",
    "    result[\"edge_p\"] = p\n",
    "    result[\"edge_p_top\"] = p_top\n",
    "    result[\"edge_p_bottom\"] = p_bottom\n",
    "    result[\"ER\"] = average_cliques_ER(k, g.number_of_nodes(), p)\n",
    "    result[\"ER_top\"] = average_cliques_ER(k, g.number_of_nodes(), p_top)\n",
    "    result[\"ER_bottom\"] = average_cliques_ER(k, g.number_of_nodes(), p_bottom)\n",
    "    \n",
    "    com = list(nx.algorithms.community.k_clique_communities(g, k))\n",
    "    com_top = list(nx.algorithms.community.k_clique_communities(g_top, k))\n",
    "    com_bottom = list(nx.algorithms.community.k_clique_communities(g_bottom, k))\n",
    "    com_strict_top = []\n",
    "    com_strict_bottom = []\n",
    "    \n",
    "    tset = set(top_nodes)\n",
    "    bset = set(bottom_nodes)\n",
    "    \n",
    "    for clique in com:\n",
    "        if len(set(clique) & tset) == len(clique):\n",
    "            com_strict_top.append(clique)\n",
    "        elif len(set(clique) & bset) == len(clique):\n",
    "            com_strict_bottom.append(sample)                               \n",
    "            \n",
    "    result[\"comms\"] = com\n",
    "    result[\"comms_top\"] = com_top\n",
    "    result[\"comms_bottom\"] = com_bottom\n",
    "    result[\"comms_strict_top\"] = com_strict_top\n",
    "    result[\"comms_strict_bottom\"] = com_strict_bottom\n",
    "    \n",
    "    return result\n",
    "\n",
    "\n",
    "def find_supercommunities(subcoms, supercoms):\n",
    "    matched_comms = []\n",
    "    for com in subcoms:\n",
    "        max_com = []\n",
    "        max_intersect = 0\n",
    "        for supercom in supercoms:\n",
    "            intersect = len(set(com) & set(supercom))\n",
    "            if intersect>max_intersect:\n",
    "                max_intersect = intersect\n",
    "                max_com = supercom\n",
    "        if max_intersect == len(com):\n",
    "            found = False\n",
    "            for com_found in matched_comms:\n",
    "                if len(set(max_com)&set(com_found))==len(max_com):\n",
    "                    found = True\n",
    "                    break\n",
    "            if not found:\n",
    "                matched_comms.append(max_com)\n",
    "            if len(max_com)==142:\n",
    "                print(com)\n",
    "                print(max_com)\n",
    "    return matched_comms"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ddfde79-306d-4986-b428-e1118fc03188",
   "metadata": {},
   "source": [
    "# The first null model (stochastic block-model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "45046efa-069e-42c0-bfe0-c5ade764154d",
   "metadata": {},
   "outputs": [],
   "source": [
    "nleft1 = len(X[X['OpinionBefore'] >= 0.6])\n",
    "nleft2 = len(X[X['OpinionAfter'] >= 0.6])\n",
    "nright1 = len(X[X['OpinionBefore'] <= 0.4])\n",
    "nright2 = len(X[X['OpinionAfter'] <= 0.4])\n",
    "\n",
    "print(f'N left before: {nleft1}')\n",
    "print(f'N left after: {nleft2}')\n",
    "print(f'N right before: {nright1}')\n",
    "print(f'N right after: {nright2}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "23266ccd-e8f5-46f1-a153-f67296ccee7c",
   "metadata": {},
   "outputs": [],
   "source": [
    "p1 = 2*G1.number_of_edges()/(G1.number_of_nodes()*(G1.number_of_nodes()-1))\n",
    "print(f'Nodes before: {G1.number_of_nodes()}\\tEdges before: {G1.number_of_edges()}')\n",
    "\n",
    "p2 = 2*G2.number_of_edges()/(G2.number_of_nodes()*(G2.number_of_nodes()-1))\n",
    "print(f'Nodes after: {G2.number_of_nodes()}\\tEdges after: {G2.number_of_edges()}')\n",
    "\n",
    "print(f'Edge probability before: {p1:.6f}')\n",
    "print(f'Edge probability after: {p2:.6f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "46b0b652-2dc9-46c7-b3ec-601d33779125",
   "metadata": {},
   "outputs": [],
   "source": [
    "k = 5\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc148726-89c6-4b07-9ee9-67df932d5938",
   "metadata": {},
   "outputs": [],
   "source": [
    "left_nodes_before = []\n",
    "left_nodes_after = []\n",
    "right_nodes_before = []\n",
    "right_nodes_after = []\n",
    "\n",
    "for idx, row in X.iterrows():\n",
    "    if row['OpinionBefore'] >= 0.6:\n",
    "        left_nodes_before.append(idx)\n",
    "    elif row['OpinionBefore'] <= 0.4:\n",
    "        right_nodes_before.append(idx)\n",
    "    if row['OpinionAfter'] >= 0.6:\n",
    "        left_nodes_after.append(idx)\n",
    "    elif row['OpinionAfter'] <= 0.4:\n",
    "        right_nodes_after.append(idx)\n",
    "\n",
    "N = len(X)\n",
    "nleft1 = len(left_nodes_before)\n",
    "nleft2 = len(left_nodes_after)\n",
    "nright1 = len(right_nodes_before)\n",
    "nright2 = len(right_nodes_after)\n",
    "        \n",
    "\n",
    "g1l = G1.subgraph(left_nodes_before)\n",
    "g1r = G1.subgraph(right_nodes_before)\n",
    "g2l = G2.subgraph(left_nodes_after)\n",
    "g2r = G2.subgraph(right_nodes_after)\n",
    "\n",
    "print(f'Left nodes before: {g1l.number_of_nodes()}\\tLeft-left edges before: {g1l.number_of_edges()}')\n",
    "print(f'Left nodes before: {g2l.number_of_nodes()}\\tLeft-left edges before: {g2l.number_of_edges()}')\n",
    "print(f'Right nodes before: {g1r.number_of_nodes()}\\tRight-right edges before: {g1r.number_of_edges()}')\n",
    "print(f'Right nodes before: {g2r.number_of_nodes()}\\tRight-right edges before: {g2r.number_of_edges()}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "49e2bc98-cd5d-4469-a001-03767f2bd15d",
   "metadata": {},
   "outputs": [],
   "source": [
    "p1 = 2*G1.number_of_edges()/(G1.number_of_nodes()*(G1.number_of_nodes()-1))\n",
    "p2 = 2*G2.number_of_edges()/(G2.number_of_nodes()*(G2.number_of_nodes()-1))\n",
    "p1l = 2*g1l.number_of_edges()/(g1l.number_of_nodes()*(g1l.number_of_nodes()-1))\n",
    "p2l = 2*g2l.number_of_edges()/(g2l.number_of_nodes()*(g2l.number_of_nodes()-1))\n",
    "p1r = 2*g1r.number_of_edges()/(g1r.number_of_nodes()*(g1r.number_of_nodes()-1))\n",
    "p2r = 2*g2r.number_of_edges()/(g2r.number_of_nodes()*(g2r.number_of_nodes()-1))\n",
    "\n",
    "print(f'Edge probability before: {p1:.6f}')\n",
    "print(f'Edge probability after: {p2:.6f}')\n",
    "print(f'Liberal-liberal edge probability before: {p1l:.6f}')\n",
    "print(f'Liberal-liberal edge probability after: {p2l:.6f}')\n",
    "print(f'Cons-cons edge probability before: {p1r:.6f}')\n",
    "print(f'Cons-cons edge probability after: {p2r:.6f}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c8ea2876-dcc6-4f65-8ece-a77033755e67",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f'Average {k}-cliques before: {average_cliques_ER(k, N, p1)}')\n",
    "print(f'Average {k}-cliques after: {average_cliques_ER(k, N, p2)}')\n",
    "print(f'Average liberal {k}-cliques before: {average_cliques_ER(k, nleft1, p1l)}')\n",
    "print(f'Average liberal {k}-cliques after: {average_cliques_ER(k, nleft2, p2l)}')\n",
    "print(f'Average conservative {k}-cliques before: {average_cliques_ER(k, nright1, p1r)}')\n",
    "print(f'Average conservative {k}-cliques after: {average_cliques_ER(k, nright2, p2r)}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb8edf82-0d23-4022-a61f-988d17164ae6",
   "metadata": {},
   "source": [
    "# The second null model"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3918cd01-4e37-4884-9ac2-da128817a1de",
   "metadata": {},
   "source": [
    "### Simulations for the first snapshot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6128bb63-8bad-4c5f-ac34-c174c7e44222",
   "metadata": {},
   "outputs": [],
   "source": [
    "opinions = list(X['OpinionBefore'])\n",
    "\n",
    "total_comms = []\n",
    "lib_comms = []\n",
    "cons_comms = []\n",
    "strict_lib_comms = []\n",
    "strict_cons_comms = []\n",
    "\n",
    "niter = 100\n",
    "for i in range(niter):\n",
    "    print(f'Simulation iteration {i+1} of {niter}...')\n",
    "    random.shuffle(opinions)\n",
    "    C_dict = communities_stats(G1, opinions, k)\n",
    "    total_comms.append(len(C_dict[\"comms\"]))\n",
    "    lib_comms.append(len(C_dict[\"comms_top\"]))\n",
    "    cons_comms.append(len(C_dict[\"comms_bottom\"]))\n",
    "    strict_lib_comms.append(len(C_dict[\"comms_strict_top\"]))\n",
    "    strict_cons_comms.append(len(C_dict[\"comms_strict_bottom\"]))\n",
    "    print('Done')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "06a55a83-587e-4165-95f7-e8033af5eb17",
   "metadata": {},
   "source": [
    "### Simulations for the second snapshot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "69652bc3-3c23-4577-92db-5f6ea83933a6",
   "metadata": {},
   "outputs": [],
   "source": [
    "opinions = list(X['OpinionAfter'])\n",
    "\n",
    "total_comms2 = []\n",
    "lib_comms2 = []\n",
    "cons_comms2 = []\n",
    "strict_lib_comms2 = []\n",
    "strict_cons_comms2 = []\n",
    "\n",
    "niter = 100\n",
    "for i in range(niter):\n",
    "    print(f'Simulation iteration {i+1} of {niter}...')\n",
    "    random.shuffle(opinions)\n",
    "    C_dict = communities_stats(G2, opinions, k)\n",
    "    total_comms2.append(len(C_dict[\"comms\"]))\n",
    "    lib_comms2.append(len(C_dict[\"comms_top\"]))\n",
    "    cons_comms2.append(len(C_dict[\"comms_bottom\"]))\n",
    "    strict_lib_comms2.append(len(C_dict[\"comms_strict_top\"]))\n",
    "    strict_cons_comms2.append(len(C_dict[\"comms_strict_bottom\"]))\n",
    "    print('Done')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d165d721-a921-4a3a-89f1-d86f496085f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "sns.histplot(x=lib_comms, kde=True, discrete=True, label='Before').set_title(f'Liberal {k}-clique communities number')\n",
    "sns.histplot(x=lib_comms2, kde=True, discrete=True, color='Red', label='After').legend()\n",
    "plt.show()\n",
    "sns.histplot(x=strict_lib_comms, kde=True, discrete=True, label='Before').set_title(f'Liberal strict {k}-clique communities number')\n",
    "sns.histplot(x=strict_lib_comms2, kde=True, discrete=True, color='Red', label='After').legend()\n",
    "plt.show()\n",
    "sns.histplot(x=cons_comms, kde=True, label='Before').set_title(f'Conservative {k}-clique communities number')\n",
    "sns.histplot(x=cons_comms2, kde=True, color='Red', label='After').legend()\n",
    "plt.show()\n",
    "sns.histplot(x=strict_cons_comms, kde=True, label='Before').set_title(f'Conservative strict {k}-clique communities number')\n",
    "sns.histplot(x=strict_cons_comms2, kde=True, color='Red', label='After').legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89f8201c-4503-49e6-82a3-de1ad5b97c40",
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f'\\nLiberal {k}-clique communities (echo-chambers):')\n",
    "print(f'Before \\tmean: {statistics.mean(strict_lib_comms):.2f}\\t stdev: {statistics.stdev(strict_lib_comms):.2f}')\n",
    "print(f'After\\tmean: {statistics.mean(strict_lib_comms2):.2f}\\t stdev: {statistics.stdev(strict_lib_comms2):.2f}')\n",
    "\n",
    "print(f'\\nConservative {k}-clique communities (echo-chambers):')\n",
    "print(f'Before\\tmean: {statistics.mean(strict_cons_comms):.2f}\\t stdev: {statistics.stdev(strict_cons_comms):.2f}')\n",
    "print(f'After\\tmean: {statistics.mean(strict_cons_comms2):.2f}\\t stdev: {statistics.stdev(strict_cons_comms2):.2f}')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
